package controllers;

import java.util.LinkedList;
import java.util.List;

import models.Dish;
import models.Order_item;
import models.Restaurant;
import models.ShoppingOrder;
import play.Logger;
import play.cache.Cache;
import play.data.validation.Min;
import play.data.validation.Required;
import play.mvc.*;

public class Shop extends Controller {
	@Before
	static void globals() {
		renderArgs.put("connected", Application.connectedCustomer());
	}

	public static void index() {
		Logger.info("Entering shopping page.");
		if (session.get("plz") == null) {
			params.flash();
			flash.error("Please enter a valid PLZ before proceeding to shopping area.");
			Application.home(null);
		}

		int plz = Integer.parseInt(session.get("plz").toString());

		String address = session.get("address").toString();
		List<Restaurant> restaurants = Restaurant.find("plz", plz).fetch();
		if (restaurants.size() > 0) {
			Logger.info("Restaurants found for the PLZ.");
			render(plz, address, restaurants);
		} else {
			session.put("plz", null);
			params.flash();
			flash.error("Unfortunately we do not have any restaurants available in the area.");
			Logger.error("No restaurants found for the PLZ.");
			Application.home(null);
		}

		render();
	}

	public static void cart() {
		Logger.info("Entering shopping cart.");		
		ShoppingOrder shop_order = Cache.get(session.getId() + "_shop_order",
				ShoppingOrder.class);

		if (shop_order == null || shop_order.order_items.size() == 0) {
			params.flash();
			flash.error("You have not selected any items to order.");
			Logger.info("Cart is empty. Redirecting to shopping page.");
			index();
		} else {
			Logger.info("Displaying shopping orders.");
			render(shop_order);
		}

	}	

	public static String addToShoppingCart(long dishID) {

		try {
			ShoppingOrder shop_order = Cache.get(session.getId()
					+ "_shop_order", ShoppingOrder.class);
			List<Order_item> orderItems;
			if (shop_order == null) {
				shop_order = new ShoppingOrder();
				orderItems = new LinkedList<Order_item>();
			} else {
				orderItems = shop_order.order_items;
			}

			Logger.info("Added to cart, dish id:" + dishID);

			Order_item order = null;
			int counter = 0;
			for (Order_item item : orderItems) {
				if (item.dish.id == dishID) {
					order = item;
					break;
				}
				counter++;
			}

			if (order == null) {
				Dish dish = Dish.findById(dishID);
				order = new Order_item(dish, 1);
				Logger.info("New order:" + order.id);
				order.calculatePrice();
				orderItems.add(order);
			}

			else {
				order.qty++;
				order.calculatePrice();
				orderItems.set(counter, order);
				Logger.info("Adding quantity to existing order");
			}

			shop_order.order_items = orderItems;
			shop_order.calculatePrice();
			Cache.set(session.getId() + "_shop_order", shop_order, "5mn");
			return "Order item NOT added to shopping cart";
		}

		catch (Exception e) {
			return "Order item NOT added to shopping cart";
		}
	}

	public static void removeOrderItem(long dishID) {

		try {
			ShoppingOrder shop_order = Cache.get(session.getId()
					+ "_shop_order", ShoppingOrder.class);
			List<Order_item> orderItems = shop_order.order_items;

			int counter = 0;
			for (Order_item item : orderItems) {
				if (item.dish.id == dishID) {
					break;
				}
				counter++;
			}
			orderItems.remove(counter);
			shop_order.order_items = orderItems;
			// shop_order.save();
			shop_order.calculatePrice();
			Cache.set(session.getId() + "_shop_order", shop_order, "5mn");
			cart();
		}

		catch (Exception e) {
		}
	}

	public static void editShoppingOrder(long dishID, @Required @Min(1) int qty) {
		try {
			Logger.info("Editing shopping order.");
			ShoppingOrder shop_order = Cache.get(session.getId()
					+ "_shop_order", ShoppingOrder.class);
			List<Order_item> orderItems = shop_order.order_items;

			int counter = 0;
			Order_item order = null;
			for (Order_item item : orderItems) {
				if (item.dish.id == dishID) {
					order = item;
					break;
				}
				counter++;
			}

			if (validation.hasErrors()) {
				params.flash();
				flash.error("Error in quantity");
			} else {
				if (qty == 0) {
					removeOrderItem(order.dish.id);
				} else {
					order.qty = qty;
					order.calculatePrice();
					orderItems.set(counter, order);
					shop_order.order_items = orderItems;
					shop_order.calculatePrice();
					Cache.set(session.getId() + "_shop_order", shop_order,
							"5mn");
				}
			}
			cart();

		} catch (Exception e) {
			Logger.error("Error when editing shopping order.", e);
			cart();
		}
	}

	public static void checkout() {
		ShoppingOrder shop_order = Cache.get(session.getId() + "_shop_order",
				ShoppingOrder.class);

		if (shop_order == null || shop_order.order_items.size() == 0) {
			params.flash();
			flash.error("You have not selected any items to order.");
			Logger.info("Cart is empty. Redirecting to shopping page.");
			index();
		} else {
			Logger.info("Entering check out page.");
			String address = session.get("address");
			render(address);
		}		
	}

	public static void confirm(@Required String name, @Required String lname, @Required String address,
			String telephone, String email, String payOption) {
		ShoppingOrder shop_order = Cache.get(session.getId()
				+ "_shop_order", ShoppingOrder.class);
		if (validation.hasErrors()) {
			validation.keep();
			params.flash();
			flash.error("Please fill up the required fields marked by *.");
			checkout();
		}
		else{
			shop_order.name = name;
			shop_order.lastName = lname;
			shop_order.delivery_address = address;
			shop_order.telephone = telephone;
			shop_order.email = email;
			save(shop_order);
			render();
		}
	}

	private static void save(ShoppingOrder shop_order){		
		for(int i = 0; i < shop_order.order_items.size(); i++){
			Order_item item = shop_order.order_items.get(i);
			item.save();
			shop_order.order_items.set(i, item);
		}
		shop_order.save();
	}
	
	public static void search(String dish) {
		Logger.info(dish);
		if (dish == null){
			index();
		}
		dish = dish.toLowerCase();
		if (dish == null || dish.isEmpty()) {
			index();
		} else {
			int plz = Integer.parseInt(session.get("plz").toString());
			List<Dish> dishes = Dish
					.find("lower(name) like ? and restaurant.plz = ? order by restaurant.name",
							"%" + dish + "%", plz).fetch();
			Logger.info("Dishes found:" + dishes.size());
			render(dishes);
		}

	}
}
